package com.tbynet.jwp.service.provider;

import java.math.BigInteger;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Page;
import com.tbynet.jwp.framework.kit.StringKit;
import com.tbynet.jwp.model.Options;
import com.tbynet.jwp.model.Postmeta;
import com.tbynet.jwp.model.Posts;
import com.tbynet.jwp.model.TermRelationships;
import com.tbynet.jwp.model.TermTaxonomy;
import com.tbynet.jwp.model.Terms;
import com.tbynet.jwp.service.PostService;

public class PostServiceProvider implements PostService {

	private Posts postDao = new Posts().dao();
	private Postmeta postmetaDao = new Postmeta().dao();
	private Options optionDao = new Options().dao();
	private Terms termDao = new Terms().dao();
	private TermTaxonomy taxonomyDao = new TermTaxonomy().dao();
	
	@Override
	public Page<Posts> search(int pageNumber, int pageSize, String type, String status, String q) {
		List<Object> paras = new ArrayList<Object>();
		StringBuilder sql = new StringBuilder("from wp_posts where 1=1");
		
		if(StrKit.notBlank(type)) {
			sql.append(" and post_type=? ");
			paras.add(type);
		}
		
		if(StrKit.notBlank(status)) {
			sql.append(" and post_status=? ");
			paras.add(status);
		} else {
			sql.append(" and post_status!=? ");
			paras.add(Posts.POST_STATUS_TRASH);
		}
		
		sql.append(" order by post_modified desc ");
		
		return postDao.paginate(pageNumber, pageSize, "select *", sql.toString(), paras.toArray());
	}

	@Override
	public Posts getPost(Object ID) {
		return postDao.findById(ID);
	}
	
	@Override
	public Posts getPost(Object ID, String type) {
		return postDao.findFirst("select * from wp_posts where ID=? and post_type=? limit 1", ID, type);
	}

	@Override
	public int count(String status) {
		List<Object> paras = new ArrayList<Object>();
		StringBuilder sql = new StringBuilder("select count(*) from wp_posts where 1=1 ");
		
		if(StrKit.notBlank(status)) {
			sql.append(" AND post_status=? ");
			paras.add(status);
		}
		
		return Db.queryInt(sql.toString(), paras.toArray());
	}

	@Override
	public List<Postmeta> getPostmetas(Object ID) {
		return postmetaDao.find("select * from wp_postmeta where post_id=?", ID);
	}

	@Override
	public List<Postmeta> getPostmetas(Object ID, String... metaKeys) {
		List<Object> paras = new ArrayList<Object>();
		StringBuilder sql = new StringBuilder("select * from wp_postmeta where post_id=?");
		paras.add(ID);
		
		for(String metaKey : metaKeys) {
			sql.append(" and meta_key=? ");
			paras.add(metaKey);
		}
		
		return postmetaDao.find(sql.toString(), paras.toArray());
	}

	@Override
	public Postmeta getPostmeta(Object ID, String metaKey) {
		return postmetaDao.findFirst("select * from wp_postmeta where post_id=? and meta_key=? limit 1", ID, metaKey);
	}

	@Override
	public boolean save(Posts post, List<Postmeta> postmetas, String format, String[] categories, String[] tags, Boolean sticky) {
		return Db.tx(new IAtom() {
			
			@Override
			public boolean run() throws SQLException {
				if(false == post.save()) {
					return false;
				}
				if(null != postmetas && false == postmetas.isEmpty()) {
					for(Postmeta meta : postmetas) {
						meta.setPostId(post.getID());
						if(false == meta.save()) {
							return false;
						}
					}
				}
				if(null != sticky && true == sticky) {
					try {
						Options option = getOption(Options.sticky_posts);
						if(null == option) {
							option = new Options();
						}
						option.setStickyPosts(post.getID().intValue());
						if(null == option.getOptionId()) {
							if(false == option.save()) {
								return false;
							}
						} else {
							if(false == option.update()) {
								return false;
							}
						}
					} catch(Exception e) {
						throw new SQLException(e);
					}
				}
				if(null != format && "0" != format) {
					String name = "post-format-" + format;
					
					Terms term = getTerm(name, TermTaxonomy.TAXONOMY_POST_FORMAT);
					if(null == term) {
						term = new Terms();
						term.setName(name);
						term.setSlug(name);
						if(false == term.save()) {
							return false;
						}
					}
					
					TermTaxonomy taxonomy = getTermTaxonomy(name, TermTaxonomy.TAXONOMY_POST_FORMAT);
					if(null == taxonomy) {
						taxonomy = new TermTaxonomy();
						taxonomy.setTaxonomy(TermTaxonomy.TAXONOMY_POST_FORMAT);
						taxonomy.setTermId(term.getTermId());
						taxonomy.setDescription("");
						if(false == taxonomy.save()) {
							return false;
						}
					}
					
					TermRelationships tr = new TermRelationships();
					tr.setObjectId(post.getID());
					tr.setTermTaxonomyId(taxonomy.getTermTaxonomyId());
					if(false == tr.save()) {
						return false;
					}
				}
				if(null != categories && 0 != categories.length) {
					for(String category : categories) {
						TermRelationships tr = new TermRelationships();
						tr.setObjectId(post.getID());
						tr.setTermTaxonomyId(new BigInteger(category));
						if(false == tr.save()) {
							return false;
						}
					}
				}
				if(null != tags && 0 != tags.length) {
					for(String tag : tags) {
						if(StrKit.isBlank(tag)) {
							continue;
						}
						
						Terms term = getTerm(tag, TermTaxonomy.TAXONOMY_POST_TAG);
						if(null == term) {
							term = new Terms();
							term.setName(tag);
							try {
								term.setSlug(StringKit.urlencode(tag));
							} catch(Exception e) {
								throw new SQLException(e);
							}
							if(false == term.save()) {
								return false;
							}
						}
						
						TermTaxonomy taxonomy = getTermTaxonomy(tag, TermTaxonomy.TAXONOMY_POST_TAG);
						if(null == taxonomy) {
							taxonomy = new TermTaxonomy();
							taxonomy.setTaxonomy(TermTaxonomy.TAXONOMY_POST_TAG);
							taxonomy.setTermId(term.getTermId());
							taxonomy.setDescription("");
							if(false == taxonomy.save()) {
								return false;
							}
						}
						
						TermRelationships tr = new TermRelationships();
						tr.setObjectId(post.getID());
						tr.setTermTaxonomyId(taxonomy.getTermTaxonomyId());
						if(false == tr.save()) {
							return false;
						}
					}
				}
				
				return true;
			}
			
		});
	}

	@Override
	public boolean update(Posts post, List<Postmeta> postmetas, String format, String[] categories, String[] tags, Boolean sticky) {
		return Db.tx(new IAtom() {
			
			@Override
			public boolean run() throws SQLException {

				return false;
			}
			
		});
	}
	
	@Override
	public boolean save(Posts post, List<Postmeta> postmetas) {
		return save(post, postmetas, null, null, null, null);
	}

	@Override
	public boolean update(Posts post, List<Postmeta> postmetas) {
		return update(post, postmetas, null, null, null, null);
	}

	@Override
	public boolean save(Posts post) {
		return post.save();
	}

	@Override
	public boolean update(Posts post) {
		return post.update();
	}
	
	private Options getOption(String name) {
		return optionDao.findFirst("select * from wp_options where option_name=? limit 1", name);
	}
	
	private Terms getTerm(String name, String taxonomy) {
		return termDao.findFirst("select a.* from wp_terms a inner join wp_term_taxonomy b on a.term_id=b.term_id where a.name=? and b.taxonomy=? limit 1", name, taxonomy);
	}
	
	private TermTaxonomy getTermTaxonomy(String name, String taxonomy) {
		return taxonomyDao.findFirst("select b.* from wp_terms a inner join wp_term_taxonomy b on a.term_id=b.term_id where a.name=? and b.taxonomy=? limit 1", name, taxonomy);
	}
	
}
